#define ALSA_PCM_NEW_HW_PARAMS_API
#define REENTRANT
#include <iostream>
#include <fstream>
#include <alsa/asoundlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdio.h>
#include "pcm.h"
#include "lsMP3.h"

using namespace std;

char message[]="In the control thread!";
snd_pcm_t *handle=0;
int con;
long sum=0;
int msgid=-1;
FILE *fp;
bool pcmPlayContinue=true;

void *control(void *arg);

int main(int argc, char * argv[])
{
	vector<string> VT;
	lsMP3(getenv("HOME"),VT);
	cout<<VT.size()<<endl;
	for(int i=0;i<VT.size();i++)
	{
		cout<<i+1<<". "<<VT[i]<<endl;
	}
	cout<<"choose the song you want to play"<<endl;
	int number;
	cin>>number;
	msgid=msgget(KEY,0666|IPC_CREAT);
	if(msgid<0)
	{
		perror("failed to create a message queue\n");
		return 0;
	}
	pthread_t a_thread;
	int res, rc, length=0, size;
	void *thread_result;
	string mp3,lrc,pcm;
	string cmd;
	mp3=VT[number-1];
	pcm=mp3.substr(0,mp3.length()-4)+".pcm";
	cmd="ffmpeg -i "+mp3+" -f s16le -acodec pcm_s16le -ac 2 -ar 44100 "+pcm;
	system(cmd.c_str());
	cout<<pcm<<endl;
	lrc=mp3.substr(0,mp3.length()-4)+".lrc";
	snd_pcm_hw_params_t *params;
	snd_pcm_uframes_t frames;
	char *buffer;
	res=pthread_create(&a_thread,NULL, control, (void*)message);
	if(res!=0)
	{
		cout<<"Failed to create a new thread!"<<endl;
		return 0;
	}	
	cmd="gnome-terminal -- ./lyricPcm "+lrc;
	pid_t child;
	if((child=fork())==-1)
	{
		perror("failure");
		return 0;
	}
	else if(child==0)
	{
		int err;
		system(cmd.c_str());
	}
	else
	{
		cout<<"in parent"<<endl;
		FILE *fp;
		rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);    
		if (rc < 0)
		{    
				printf("unable to open pcm device\n");  
				return -1;  
		}
		snd_pcm_hw_params_alloca(&params);
		snd_pcm_hw_params_any(handle, params);
		snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
		snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);  
		snd_pcm_hw_params_set_channels(handle, params, 2); 
		unsigned int val = 44100;    
		snd_pcm_hw_params_set_rate_near(handle, params, &val, 0); 
		rc = snd_pcm_hw_params(handle, params);    
		if (rc < 0) {    
			printf("unable to set hw parameters: %s\n", snd_strerror(rc));    
			exit(1);    
		}
		snd_pcm_hw_params_get_period_size(params, &frames, 0);    
		if(frames<4410)
			frames=4410;
		frames*=6;
		size = frames * 4;
		buffer = (char *)malloc(size);
		fp=fopen(pcm.c_str(),"rb");
		if(!fp)
		{
			perror("error\n");
			return 0;
		}
		while(!feof(fp)  && pcmPlayContinue)
		{
			length=fread(buffer,1,size,fp);
			rc = snd_pcm_writei(handle, buffer, length/4);
			if (rc == -EPIPE) {    
				printf("underrun occured\n");    
			}    
			else if (rc < 0) {    
				printf("error from writei: %s\n", snd_strerror(rc));    
			}   
 		sum+=length/4;
		}
		cout<<"out"<<endl;
		if(pcmPlayContinue)
			snd_pcm_drain(handle);    
		snd_pcm_close(handle);    
		free(buffer);
		fclose(fp);
	}
	return 0;
}

void *control(void *arg)
{
	Mymsg mymsg;
	int nbytes;
	char p;
	cout<<"You can type in \"p\" to stop playing the song!"<<endl;
	while(1)
	{
		cin>>p;
		long delay;
		if(handle!=0)
		{
			snd_pcm_delay(handle,&delay);
		}
		if(p=='p')
		{
			snd_pcm_pause(handle,1);
			mymsg.mytype=PAUSE;
			nbytes=0;
		}
		else if(p=='c')
		{
			snd_pcm_pause(handle,0);
			mymsg.mytype=RESUME;
			nbytes=0;
		}
		else if(p=='q')
		{
			q();
			mymsg.mytype=EXIT;
			nbytes=0;
			pcmPlayContinue=false;
		}
		cout<<"message sent: "<<mymsg.mytype<<endl;
		msgsnd(msgid,&mymsg,nbytes,0);
	}
}
